#pragma once
#include <cstring>
#include <sstream>
#include <string>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <unordered_map>
#include <fstream>
#include <algorithm> // 必须添加此头文件
#include <cctype>    // 用于::tolower
#include "Log.hpp"
struct Requset;

#define SEP "\r\n"

namespace  Util
{
    // 支持大文件分块读取


 std::string static SanitizePath(const std::string& path) {
        std::vector<std::string> parts;
        std::istringstream iss(path);
        std::string part;
        
        while (std::getline(iss, part, '/')) {
            if (part == "..") {
                if (!parts.empty()) parts.pop_back();
            } else if (!part.empty() && part != ".") {
                parts.push_back(part);
            }
        }
        
        std::string result;
        for (const auto& p : parts) {
            result += "/" + p;
        }
        return result.empty() ? "/" : result;
    }

    // URL解码实现
    std::string static URLDecode(const std::string& encoded) {
        std::ostringstream decoded;
        for (size_t i = 0; i < encoded.size(); ++i) {
            if (encoded[i] == '%' && i + 2 < encoded.size()) {
                int hex_val;
                std::istringstream hex_stream(encoded.substr(i+1, 2));
                if (hex_stream >> std::hex >> hex_val) {
                    decoded << static_cast<char>(hex_val);
                    i += 2;
                } else {
                    decoded << encoded[i];
                }
            } else if (encoded[i] == '+') {
                decoded << ' ';
            } else {
                decoded << encoded[i];
            }
        }
        return decoded.str();
    }

    // 资源加载实现（修正LoadSorce拼写错误）
    bool static LoadResource(const std::string& path, std::string& content) {
        std::ifstream file(path, std::ios::binary);
        if (!file) return false;
        
        content.assign((std::istreambuf_iterator<char>(file)), 
                      std::istreambuf_iterator<char>());
        return true;
    }

    // MIME类型识别实现
    std::string static GetMimeType(const std::string& path) {
        static const std::unordered_map<std::string, std::string> mime_db = {
            {".html", "text/html; charset=utf-8"},
            {".css",  "text/css"},
            {".js",   "application/javascript"},
            {".png",  "image/png"},
            {".jpg",  "image/jpeg"},
            {".jpeg", "image/jpeg"},
            {".gif",  "image/gif"},
            {".mp3",  "audio/mpeg"},
            {".mp4",  "video/mp4"},
            {".mp3",  "audio/mpeg"},  // 新增音乐类型支持
             {".md",   "text/markdown"} // README.md支持
        };

        size_t dot_pos = path.find_last_of('.');
        if (dot_pos != std::string::npos) {
            std::string ext = path.substr(dot_pos);
            std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
            auto it = mime_db.find(ext);
            return (it != mime_db.end()) ? it->second : "application/octet-stream";
        }
        return "application/octet-stream";
    }














    // 这里有一个小坑！
    // 资源不仅仅有html资源，也有音频图片，这些资源是二进制的！
    // 所以我们要保证我们body能够保存所有的二进制序列。
    //  int stat(const char *pathname, struct stat *statbuf);
    static bool LoadSorce(std::string &body, std::string path)
    {
        // 1.获取资源文件的大小
        struct stat attribute;
        int n = stat(path.c_str(), &attribute);
        if (n < 0)
        {
            logMessage(Warning,"stat fail... path: %s",path.c_str());
            return false;
        }
        // 2.设置body的大小
        int sz = attribute.st_size;
        body.resize(sz);
        // 3.读取
        int fd = open(path.c_str(),O_RDONLY);
        ssize_t s = read(fd,(char*)body.c_str(),sz);
        if(s < 0)
        {
            logMessage(Warning,"read fail...");
            return false;
        }
        logMessage(Info,"read success...\n %s",body.c_str());
        return true;
    }



    
    //读取一行
    static std::string ReadLine(const std::string& sep,std::string& mess)
    {
        auto pos = mess.find(SEP,0);
        std::string s = mess.substr(0,pos);
        mess.erase(0,pos); //将读取的一行，从mess中截掉，方便下次截取下一行
        return s;
    }

    static std:: string GetType(std::string url)
    {
        // 你可以使用unordered_map去构造一下 映射表
        // 这里我们简单的映射一下
        ssize_t n = url.size();
        auto pos = url.rfind(".",n);
        std::string suffix = url.substr(pos,n - pos);
        logMessage(Debug,"suffix: %s",suffix.c_str());
        if(suffix == ".html" || suffix == ".htm")
            return "text/html";
        else if(suffix == ".jpeg" || suffix == ".jpg" )
            return "image/jpeg";
        else if(suffix == ".png")
            return "image/png";
        else if(suffix == ".gif")
            return "image/gif";
        else if(suffix == ".css")
            return "text/css";
        else if(suffix == ".js")
            return "application/x-javascript";
        else if(suffix == ".mp3")
            return "audio/mp3";
        return "";

    }
    static bool SplitFirstLine(const std::string& line,std::string* method,std::string* url,std::string* ver)
    {
        // 使用ssteram库中的,stringstream分割字符串
        // 哭死 就两行
        std:: stringstream ss(line);
        ss >> *method >> *url >> *ver;

        //通过find，substr 提取子串
        // // logMessage(Debug,"line: ",line.c_str());
        // std::string sep = " ";
        // // int step = sizeof(sep); // 我醉了，这是字符串你要求的是长度，用的是strlen啊！
        // int step = strlen(sep.c_str()); 
        // size_t start = 0;
        // size_t pos = line.find(sep,start); 
        // logMessage(Debug,"pos %d %c",pos,line[pos]);  // 3

        // *method = line.substr(start,pos - start); 
        // std::cout << "method: " << *method << std:: endl;
        // // GET / HTTP/1.0
        // start = pos + step; // 11
        // logMessage(Info,"start %d %c",start,line[start]);


        // pos = line.find(sep,start);
        // logMessage(Debug,"pos %d %c",pos,line[pos]);

        // *url = line.substr(start,pos - start);
        // std::cout << "url: " << *url << std:: endl;

        // start = pos + step;

        // logMessage(Info,"start %d %c",start,line[start]);
        // pos = line.find(sep,start);
        // logMessage(Debug,"pos %d %c",pos,line[pos]);

        // *ver = line.substr(start,pos - start);
        // std::cout << "ver: " << *ver << std:: endl;
        return true;
    }
};